package com.ymx.darling.util;

import com.ymx.darling.exception.DarlingException;
import com.ymx.darling.exception.ExceptionFactory;
import com.ymx.darling.session.setting.Context;

import java.sql.Array;
import java.sql.SQLException;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

public class StringUtil {

    /**
     * 判断字符串为null  或者为空串
     * @param s 字符串
     * @return boolean
     */
    public static boolean isNull(String s){
        return s == null || s.isEmpty();
    }


    /**
     * 判断字符串不为null或空串
     * @param s 字符串
     * @return boolean
     */
    public static boolean isNoNull(String s){
        return s != null && !s.isEmpty();
    }



    /**
     * 将 List 中的字符串按照指定的分隔符连接起来
     * @param delimiter 分隔符
     * @param list 字符串列表
     * @return 连接后的字符串
     */
    public static String join(String delimiter, List<String> list) {
        StringBuilder sb = new StringBuilder();
        if (list != null && !list.isEmpty()) {
            for (int i = 0; i < list.size(); i++) {
                sb.append(list.get(i));
                if (i < list.size() - 1) {
                    sb.append(delimiter);
                }
            }
        }
        return sb.toString();
    }


    /**
     * 截取指定字符串后的子串
     * @param str 模板字符串 例如 getName
     * @param regx 提取的约定(正则提取)
     * @return  截取后的子串 如 Name
     */
    public static String last(String str, String regx){
        return str.replaceFirst(regx,"");
    }


    /**
     * 将驼峰式命名转换为下划线命名
     * @param str String 转换前的字符串 如 stuName
     * @return String 转换后的字符串 如 stu_name
     */
    public static String mapUnderscoreToCamelCase(String str){
        String regex = "([a-z])([A-Z]+)";
        String replacement = "$1_$2";
        return str.replaceAll(regex, replacement).toLowerCase();
    }


    /**
     * 替换内容
     * @param context 替换的内容
     * @param oldString 被替换的内容
     * @param newString 新的内容
     * @return 返回替换后的字符串
     */
    public static String replace(String context,String oldString, String newString) {
        return context.replace(oldString, newString);
    }


    /**
     * 返回一个实体的字符串表现形式
     * @param object obj
     * @return String
     */
    public static String toString(Object object) {
        if (object instanceof Array) {
            try {
                return ArrayUtil.toString(((Array) object).getArray());
            } catch (SQLException e) {
                return object.toString();
            }
        }
        return ArrayUtil.toString(object);
    }


    public static String methodToProperty(String name) {
        if (name.startsWith("is")) {
            name = name.substring(2);
        } else {
            if (!name.startsWith("get") && !name.startsWith("set")) {
                DarlingException darlingException = new DarlingException(String.format("Error parsing property name '%s'.  Didn't start with 'is', 'get' or 'set'.", name));
                String reason = "方法名转属性名时抛出异常";
                throw ExceptionFactory.wrapException(reason, darlingException);
            }

            name = name.substring(3);
        }

        if (!name.isEmpty()) {
            name = name.substring(0, 1).toLowerCase(Locale.ENGLISH).concat(name.substring(1));
        }

        return name;
    }


    /**
     * 判断方法是否以set开头
     * @param methodName 方法名
     * @return boolean
     */
    public static boolean isSetterMethod(String methodName) {
        return Objects.nonNull(methodName) && methodName.startsWith("set");
    }


    /**
     * 判断字符串中是否存在指定字符
     * @param string 字符串
     * @param c 待查询的字符
     * @return boolean
     */
    public static boolean containsChar(String string, char c){
        return string.indexOf(c) != -1;
    }


    /**
     * 将诸如table.column或table.`column`的字符串分割为[table,column]
     * @param tableAndColumn 带表名的字段名称
     * @return str[]
     */
    public static String[] splitTableAndColumn(String tableAndColumn){
        String[] split = tableAndColumn.split("\\.");
        if (split.length == 2) {
            split[1] = removeBackticks(split[1]);
            return split;
        }
        return new String[]{tableAndColumn};
    }


    /**
     * 去除字符串两侧的反引号
     * @param input str
     * @return str
     */
    private static String removeBackticks(String input) {
        if (input == null || input.length() < 2) {
            return input; // 如果输入为空或长度小于2，不需要处理
        }
        if (input.startsWith("`") && input.endsWith("`")) {
            return input.substring(1, input.length() - 1);
        }
        return input; // 如果不以反引号开头和结尾，则返回原字符串
    }


    /**
     * 将字段名拼接为get方法名
     *
     * @param fieldName 字段名
     * @return 对应的get方法名
     */
    public static String generateGetterMethodName(String fieldName) {
        if (fieldName == null || fieldName.isEmpty()) {
            throw new IllegalArgumentException("待转换的字段不能为null");
        }
        // 将字段名首字母大写
        String firstLetterUpper = fieldName.substring(0, 1).toUpperCase(Locale.ROOT) + fieldName.substring(1);
        // 拼接为get方法名
        return "get" + firstLetterUpper;
    }


    /**
     * 去除字符串的前缀
     * @param input 原始字符串
     * @param prefix 要去除的前缀
     * @return 去除前缀后的字符串
     */
    public static String removePrefix(String input, String prefix) {
        if (input == null || prefix == null) {
            throw new IllegalArgumentException("字符串上下文或前缀字符串不能为null");
        }

        // 检查字符串是否以指定前缀开头
        if (input.startsWith(prefix)) {
            // 去除前缀并返回结果
            return input.substring(prefix.length());
        }

        // 如果没有前缀，直接返回原始字符串
        return input;
    }


    /**
     * 去除字符串的后缀
     * @param input 原始字符串
     * @param suffix 要去除的后缀
     * @return 去除后缀后的字符串
     */
    public static String removeSuffix(String input, String suffix) {
        if (input == null || suffix == null) {
            throw new IllegalArgumentException("字符串上下文或后缀字符串不能为null");
        }

        // 检查字符串是否以指定后缀结尾
        if (input.endsWith(suffix)) {
            // 去除后缀并返回结果
            return input.substring(0, input.length() - suffix.length());
        }

        // 如果没有后缀，直接返回原始字符串
        return input;
    }


    /**
     * 替换字符串中完全匹配的单词
     * @param input 原始字符串
     * @param target 要替换的目标单词
     * @param replacement 替换后的单词
     * @return 替换后的字符串
     */
    public static String replaceWholeWord(String input, String replacement, String target) {
        // 参数都不能为null或者空串
        if (isNull(input) || isNull(target) || isNull(replacement)) {
            return input;
        } else {
            StringBuilder contextBuilder = new StringBuilder(); // 保存替换后的内容
            StringBuilder itemBuilder = new StringBuilder(); // 保存单词项的内容
            char item;
            for (int len = input.length(), itemIndex = 0; itemIndex < len; ++itemIndex) {
                item = input.charAt(itemIndex);
                // 判断item属于变量名
                if (Character.isLetterOrDigit(item) || item == '_') {
                    itemBuilder.append(item);
                } else {
                    // 判断内容是否替换为目标字符串
                    if (itemBuilder.length() > 0) {
                        String itemName = itemBuilder.toString();
                        if (itemName.equals(replacement)) {
                            contextBuilder.append(target);
                        } else {
                            contextBuilder.append(itemName);
                        }
                        itemBuilder = new StringBuilder();
                    }
                    contextBuilder.append(item);
                }
            }
            return contextBuilder.toString();
        }
    }

    /**
     * 创建sql语句的id
     * @return String 如果当前未指定{@code namespace}和{@code mapperMethod} 则返回null
     */
    public static String createStatementIdWithMapperMethod() {
        if (Context.hasNamespace() && Context.hasMapperMethod()) {
            return Context.getNamespace().getName() + "." + Context.getMapperMethod().getName();
        }
        return null;
    }


    /**
     * 获取第一个被 (空格 \n \r \t) 分割的子串
     * @param input input
     * @return String
     */
    public static String extractFirstSubstring(String input) {
        if (input == null) {
            return "";
        }

        final int length = input.length();
        if (length == 0) {
            return "";
        }

        int i = 0;
        // 快速跳过常见空白字符
        while (i < length) {
            char c = input.charAt(i);
            if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
                break;
            }
            i++;
        }

        if (i >= length) {
            return "";
        }

        final int start = i;
        // 快速扫描非空白字符
        while (i < length) {
            char c = input.charAt(i);
            if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                break;
            }
            i++;
        }

        return input.substring(start, i);
    }
}
